package com.easylinkin.linkappapi.analyze.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.analyze.entity.AnalyzeDateSource;
import com.easylinkin.linkappapi.analyze.entity.DdeviceVo;
import com.easylinkin.linkappapi.analyze.mapper.AnalyzeDateSourceMapper;
import com.easylinkin.linkappapi.analyze.service.AnalyzeDateSourceService;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.mapper.DeviceMapper;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 设备资产表，关联两张表
 * 关联1  资产表-资产设备表
 * 关联2  资产表-资产用户表
 * 服务实现类
 * </p>
 *
 * @author XuGuoQing
 * @since 2020-04-23
 */
@Service
public class AnalyzeDateSourceServiceImpl extends ServiceImpl<AnalyzeDateSourceMapper, AnalyzeDateSource> implements AnalyzeDateSourceService {

    private static final int TEANT_TYPE = 0;
    private static final int AREA_TYPE = 1;
    private static final int DEVICE_TYPE = 2;
    private static final int NO_DELETE = 1;
    private static final int ON_STATUS = 1;
    private static final int OFF_STATUS = 0;

    @Resource
    private CommonService commonService;

    @Resource
    DeviceMapper deviceMapper;

    @Resource
    LinkappUserContextProducer linkappUserContextProducer;

    @Override
    public boolean addAnalyzeDateSource(AnalyzeDateSource analyzeDateSource) {
        validParamFormat(analyzeDateSource);
        Assert.isTrue(ifDateSourceNotExist(analyzeDateSource.getDatasourceName()), "数据源名称不能重复");
        analyzeDateSource.setDeviceIdString("");
        if (!ObjectUtils.isEmpty(analyzeDateSource.getDeviceIdList())) {
            List listDeviceId = getExistedDeviceId(analyzeDateSource.getDeviceIdList());
            if (!ObjectUtils.isEmpty(listDeviceId)) {
                String deviceIdString = StringUtils.join(listDeviceId.stream().map(Object::toString).toArray(String[]::new), ",");
                analyzeDateSource.setDeviceIdString(deviceIdString);
            }
        }
        if (analyzeDateSource.getTenantId() == null) {
            commonService.setCreateAndModifyInfo(analyzeDateSource);
            LinkappUser user = linkappUserContextProducer.getCurrent();
            analyzeDateSource.setTenantId(user.getTenantId());
        }
        return this.save(analyzeDateSource);
    }

    @Override
    public boolean deleteAnalyzeDateSource(List<String> dateSourceIdList) {
        Assert.notEmpty(dateSourceIdList, "删除的数据源列表不能为空");
        baseMapper.deleteBatchIds(dateSourceIdList);
        return true;
    }


    @Override
    public boolean updateAnalyzeDateSource(AnalyzeDateSource analyzeDateSource) {
        Assert.notNull(analyzeDateSource.getId(), "数据源ID不能为空");
        AnalyzeDateSource analyzeDateSourceExist = baseMapper.selectById(analyzeDateSource.getId());
        validParamFormat(analyzeDateSource);
        Assert.notNull(analyzeDateSourceExist, "数据源不存在");
        boolean iseDateSourceNotRepeat = ifDateSourceNotExist(analyzeDateSource.getDatasourceName()) || analyzeDateSource.getDatasourceName().equals(analyzeDateSourceExist.getDatasourceName());
        Assert.isTrue(iseDateSourceNotRepeat, "数据名称不能重复");
        analyzeDateSource.setDeviceIdString(null);
        commonService.setModifyInfo(analyzeDateSource);
        return this.updateById(analyzeDateSource);
    }


    @Override
    public boolean updateAnalyzeDateStatus(AnalyzeDateSource analyzeDateSource) {
        AnalyzeDateSource analyzeDateSourceExist = baseMapper.selectById(analyzeDateSource.getId());
        Assert.notNull(analyzeDateSourceExist, "数据源不存在");
        Assert.notNull(analyzeDateSource.getStatus(), "数据源状态不能为空");
        Assert.isTrue(analyzeDateSource.getStatus() == ON_STATUS || analyzeDateSource.getStatus() == OFF_STATUS, "资产状态值不符要求");
        analyzeDateSourceExist.setStatus(analyzeDateSource.getStatus());
        commonService.setModifyInfo(analyzeDateSourceExist);
        return this.updateById(analyzeDateSourceExist);
    }


    @Override
    public AnalyzeDateSource getDateSourceById(AnalyzeDateSource analyzeDateSource) {
        Assert.notNull(analyzeDateSource.getId(), "数据源id不能为空");
        return baseMapper.selectById(analyzeDateSource.getId());
    }

    @Override
    public List<AnalyzeDateSource> getDateSourceList() {
        return this.list(new QueryWrapper<AnalyzeDateSource>().eq("status", ON_STATUS).orderByAsc("datasource_type"));
    }

    @Override
    public List<AnalyzeDateSource> getDateSources(AnalyzeDateSource analyzeDateSource) {
        Assert.notNull(analyzeDateSource, "参数为空");
        analyzeDateSource.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getDateSources(analyzeDateSource);
    }


    @Override
    public IPage<AnalyzeDateSource> getPage(IPage page, AnalyzeDateSource analyzeDateSource) {
        Assert.notNull(page, "分页数据不能为空");
        Assert.notNull(analyzeDateSource, "查询对象不能为空");
        return baseMapper.getDataSourcList(page, analyzeDateSource);
    }

    @Override
    public IPage<Device> getDeviceByDataSourceId(IPage page, DdeviceVo deviceVo) {
        Assert.notNull(page, "分页数据不能为空");
        Assert.notNull(deviceVo, "查询对象不能为空");
        Assert.notNull(deviceVo.getBuddingFlag(), "查询绑定标志位为空");
        String buddingFlag = deviceVo.getBuddingFlag();
        Assert.isTrue("budding".equals(buddingFlag) || "nobudding".equals(buddingFlag) || "".equals(buddingFlag), "查询绑定标志位输入有误");


        return baseMapper.getDeviceByDataSourceId(page, deviceVo);
    }

    @Override
    public boolean addDeviceToDateSource(AnalyzeDateSource analyzeDateSource) {
        if (ObjectUtils.isEmpty(analyzeDateSource.getDeviceIdList())) {
            return true;
        }
        AnalyzeDateSource analyzeDateSourceExist = baseMapper.selectById(analyzeDateSource.getId());
        Assert.notNull(analyzeDateSourceExist, "数据源不存在");
        List<String> listFinal = new ArrayList<>();

        if (!ObjectUtils.isEmpty(analyzeDateSourceExist.getDeviceIdString())) {
            listFinal = new ArrayList(Arrays.asList(analyzeDateSourceExist.getDeviceIdString().split(",")));
        }
        listFinal.addAll(analyzeDateSource.getDeviceIdList());
        listFinal = listFinal.stream().distinct().collect(Collectors.toList());
        listFinal = getExistedDeviceId(listFinal);

        String deviceIdString = "";
        if (!ObjectUtils.isEmpty(listFinal)) {
            deviceIdString = StringUtils.join(listFinal.stream().map(Object::toString).toArray(String[]::new), ",");
        }
        analyzeDateSourceExist.setDeviceIdString(deviceIdString);

        return this.updateById(analyzeDateSourceExist);
    }

    @Override
    public boolean removeDeviceFromDateSource(AnalyzeDateSource analyzeDateSource) {

        if (ObjectUtils.isEmpty(analyzeDateSource.getDeviceIdList())) {
            return true;
        }
        List<String> listFinal = new ArrayList<>();

        AnalyzeDateSource analyzeDateSourceExist = baseMapper.selectById(analyzeDateSource.getId());
        if (!ObjectUtils.isEmpty(analyzeDateSourceExist.getDeviceIdString())) {
            listFinal = new ArrayList<>(Arrays.asList(analyzeDateSourceExist.getDeviceIdString().split(",")));
        }

        listFinal.removeAll(analyzeDateSource.getDeviceIdList());
        String deviceIdString = "";

        if (!ObjectUtils.isEmpty(listFinal)) {
            listFinal = listFinal.stream().distinct().collect(Collectors.toList());
            listFinal = getExistedDeviceId(listFinal);
            if (!ObjectUtils.isEmpty(listFinal)) {
                deviceIdString = StringUtils.join(listFinal.stream().map(Object::toString).toArray(String[]::new), ",");
            }
        }
        analyzeDateSourceExist.setDeviceIdString(deviceIdString);

        return this.updateById(analyzeDateSourceExist);
    }


    @Override
    public List<String> getExistedDeviceId(List<String> deviceIdList) {
        QueryWrapper<Device> wrapper = new QueryWrapper();
        wrapper.in("id", deviceIdList);
        wrapper.eq("delete_state", 1);
        List<Device> deviceList = deviceMapper.selectList(wrapper);
        return deviceList.stream().map(Device::getId).collect(Collectors.toList());

    }

    @Override
    public List<String> getExistedDeviceCode(List<String> deviceIdList) {
        QueryWrapper<Device> wrapper = new QueryWrapper();
        wrapper.in("id", deviceIdList);
        wrapper.eq("delete_state", 1);
        List<Device> deviceList = deviceMapper.selectList(wrapper);
        return deviceList.stream().map(Device::getCode).collect(Collectors.toList());

    }


    /**
     * 校验参数格式
     */

    private void validParamFormat(AnalyzeDateSource analyzeDateSource) {
        Assert.notNull(analyzeDateSource, "添加参数不能为空");
        Assert.notNull(analyzeDateSource.getDatasourceType(), "数据源类型不能为空");
        Assert.notNull(analyzeDateSource.getDatasourceName(), "数据源名称不能为空");
        Assert.notNull(analyzeDateSource.getDatasourceDesc(), "数据源描述不能为空");
        Assert.notNull(analyzeDateSource.getStatus(), "数据源状态不能为空");
        if (analyzeDateSource.getDatasourceType() == AREA_TYPE) {
            Assert.notNull(analyzeDateSource.getAreaId(), "空间位置不能为空");
        }
        Assert.isTrue(analyzeDateSource.getStatus() == ON_STATUS || analyzeDateSource.getStatus() == OFF_STATUS, "资产状态值不符要求");
        Assert.isTrue(analyzeDateSource.getDatasourceName().length() <= 32, "name超长");
        Assert.isTrue(analyzeDateSource.getDatasourceDesc().length() <= 255, "资产描述超长，不得长于255个字符");
        Assert.isTrue(analyzeDateSource.getDatasourceType() == TEANT_TYPE||analyzeDateSource.getDatasourceType() == AREA_TYPE || analyzeDateSource.getDatasourceType() == DEVICE_TYPE, "数据源类型不对");

    }


    boolean ifDateSourceNotExist(String datasourceName) {
        QueryWrapper<AnalyzeDateSource> wrapper = new QueryWrapper<>();
        wrapper.eq("datasource_name", datasourceName).eq("delete_state", NO_DELETE);
        List<AnalyzeDateSource> assetExist = this.list(wrapper);
        return assetExist.size() == 0;
    }


}
